package com.yikes.srb.web.utils.password;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

/**
 * <p>
 * 加密
 * </p>
 *
 * @Author: guanrong.yin
 * @Date: 2024/12/31 11:25
 * @Version: 1.0
 */
@Slf4j
public class EncryptUtil {


    // 密匙，必须16位
    private static final String KEY = "147258369abcdefg";

    // 偏移量
    private static final String OFFSET = "1234567891234567";

    // 编码
    private static final String ENCODING = "UTF-8";

    //算法
    private static final String ALGORITHM = "AES";

    // 默认的加密算法，CBC模式
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";

    /**
     * AES加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String AESEncrypt(String data) {

        try {

            //指定算法、获取Cipher对象(DES/CBC/PKCS5Padding：算法为，工作模式，填充模式)
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            //根据自定义的加密密匙和算法模式初始化密钥规范
            SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes(StandardCharsets.US_ASCII), ALGORITHM);
            //CBC模式偏移量IV
            IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
            //初始化加密模式
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            //单部分加密结束，重置Cipher
            byte[] encrypted = cipher.doFinal(data.getBytes(ENCODING));
            //加密后再使用BASE64做转码
            return new Base64().encodeToString(encrypted);

        } catch (InvalidAlgorithmParameterException e) {

            log.warn("加密出错-InvalidAlgorithmParameterException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {

            log.warn("加密出错-NoSuchPaddingException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {

            log.warn("加密出错-IllegalBlockSizeException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {

            log.warn("加密出错-UnsupportedEncodingException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {

            log.warn("加密出错-NoSuchAlgorithmException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {

            log.warn("加密出错-BadPaddingException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {

            log.warn("加密出错-InvalidKeyException:{}", e.getMessage());
            throw new RuntimeException(e);
        }

    }

    /**
     * AES解密
     *
     * @param data
     * @return String
     * @author tao
     * @date 2021-6-15 16:46:07
     */
    public static String AESDecrypt(String data) {

        try {
            //指定算法、获取Cipher对象(DES/CBC/PKCS5Padding：算法为，工作模式，填充模式)
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            //根据自定义的加密密匙和算法模式初始化密钥规范
            SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes(StandardCharsets.US_ASCII), ALGORITHM);
            //CBC模式偏移量IV
            IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
            //初始化解密模式
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            //先用base64解码
            byte[] buffer = new Base64().decode(data);
            //单部分加密结束，重置Cipher
            byte[] encrypted = cipher.doFinal(buffer);
            return new String(encrypted, ENCODING);
        } catch (InvalidAlgorithmParameterException e) {

            log.warn("加密出错-InvalidAlgorithmParameterException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {

            log.warn("加密出错-NoSuchPaddingException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {

            log.warn("加密出错-IllegalBlockSizeException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {

            log.warn("加密出错-UnsupportedEncodingException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {

            log.warn("加密出错-NoSuchAlgorithmException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {

            log.warn("加密出错-BadPaddingException:{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {

            log.warn("加密出错-InvalidKeyException:{}", e.getMessage());
            throw new RuntimeException(e);
        }

    }

    /**
     * 验证密码
     *
     * @param password  未加密数据-前端传送
     * @param encrypted 已经加密的数据
     */
    public static Boolean verify(String password, String encrypted) throws Exception {

        return encrypted.equals(AESEncrypt(password));

    }


    public static void main(String[] args) throws Exception {

        String encrypt = AESEncrypt("654321");
        System.out.println("encrypt = " + encrypt);

        String decrypt = AESDecrypt(encrypt);
        System.out.println("decrypt = " + decrypt);

        boolean equals = Objects.equals("jTXXJELo5gwQAprF5GBEag==", "jTXXJELo5gwQAprF5GBEag==");
        System.out.println("equals = " + equals);
    }


}
